#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>

#include <share.h>

#define MAX_MSGSIZE 1024

void kmsg_main(int sd) 
{
	struct sockaddr_nl daddr;
	struct nlmsghdr *nlh = NULL;
	struct msghdr msg;
	struct iovec iov;
	int ret = 0;

	memset(&daddr, 0, sizeof(daddr));

	nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_MSGSIZE));
	if (!nlh) {
		fprintf(stderr, "Alloc netlink header failed");
		return;
	}

	while (1) {
		memset(nlh, 0, NLMSG_SPACE(MAX_MSGSIZE));

		iov.iov_base = (void *)nlh;
		iov.iov_len = NLMSG_SPACE(MAX_MSGSIZE);
		msg.msg_name = (void *)&daddr;
		msg.msg_namelen = sizeof(daddr);
		msg.msg_iov = &iov;
		msg.msg_iovlen = 1;

		ret = recvmsg(sd, &msg, 0);
		if (ret == 0) {
			printf("Exit.\n");
			exit(0);
		} else if (ret == 0) {
			perror("recvmsg:");
			exit(1);
		}
		printf("%s", (char *)NLMSG_DATA(nlh));
	}
}

int main(void)
{
	struct sockaddr_nl saddr;
	int sd;
	int ret = 0;

	memset(&saddr, 0, sizeof(saddr));
	saddr.nl_family = AF_NETLINK;      
	saddr.nl_pid = getpid();
	saddr.nl_groups = 1;

	errno = 0;
	sd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KMSG);
	if (sd < 0) {
		fprintf(stderr, "Create socket failed:%s", strerror(errno));
		ret = sd;
		goto socket_fail;
	}

	errno = 0;
	ret = bind(sd, (struct sockaddr*)&saddr, sizeof(saddr));
	if (ret < 0) {
		fprintf(stderr, "Bind socket failed:%s", strerror(errno));
		goto bind_fail;
	}

	kmsg_main(sd);

bind_fail:
	close(sd);
socket_fail:
	return ret;
}

